package cn.com.sinux.spring.utils;

/**
 * Created by wangjie on 2016/3/22.
 */

import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.util.*;

/**
 * xml相关的工具类
 *
 * @author yang.y
 */
@SuppressWarnings("unchecked")
public class XmlUtils {

    public static Document xmlStrToDoc(String xmlStr) throws Exception {
        return DocumentHelper.parseText(xmlStr);
    }

    public static Map<String, Object> xmlPathToMap(String xmlPath) throws Exception {
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(xmlPath));
        return docToMap(document);
    }

    public static Map<String, Object> docToMap(Document doc) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (doc == null)
            return map;
        Element root = doc.getRootElement();
        map.put(root.getName(), strToMap(root));
        return map;
    }


    public static Map strToMap(Element e) {
        Map map = new Hashtable();
        List list = e.elements();
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Element iter = (Element) list.get(i);
                List mapList = new ArrayList();
                if (iter.elements().size() > 0) {
                    Map m = strToMap(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), m);
                    }
                } else {
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(parserElementAttributeToMap(iter));
                        } else if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(parserElementAttributeToMap(iter));
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), parserElementAttributeToMap(iter));
                    }

                }
            }
        }
        if (StringUtils.isNotBlank(e.getText())) {
            map.put("value", e.getText().trim());
        }
        return map;
    }

    /**
     * 把标签中的属性解析为Map
     *
     * @param element
     * @return
     */
    private static Map<String, String> parserElementAttributeToMap(Element element) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("value", element.getText());
        Iterator iterator = element.attributeIterator();
        while (iterator.hasNext()) {
            Attribute attr = (Attribute) iterator.next();
            map.put(attr.getName(), attr.getValue());
        }
        return map;
    }

    /**
     * 将Map对象通过反射机制转换成Bean对象
     *
     * @param map   存放数据的map对象
     * @param clazz 待转换的class
     * @return 转换后的Bean对象
     * @throws Exception 异常
     */
    public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) throws Exception {
        T obj = clazz.newInstance();
        if (map != null && map.size() > 0) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                String propertyName = entry.getKey();
                Object value = entry.getValue();
                String setMethodName = "set"
                        + propertyName.substring(0, 1).toUpperCase()
                        + propertyName.substring(1);
                Field field = getClassField(clazz, propertyName);
                if (field != null) {
                    Class fieldTypeClass = field.getType();
                    value = convertValType(value, fieldTypeClass);
                    String result;
                    if (value instanceof HashMap) {
                        HashMap mm = (HashMap) value;
                        result = String.valueOf(mm.get("value"));
                    } else {
                        result = String.valueOf(value);
                    }
                    clazz.getMethod(setMethodName, field.getType()).invoke(obj, result);
                }
            }
        }
        return obj;
    }

    /**
     * 将Object类型的值，转换成bean对象属性里对应的类型值
     *
     * @param value          Object对象值
     * @param fieldTypeClass 属性的类型
     * @return 转换后的值
     */
    private static Object convertValType(Object value, Class fieldTypeClass) {
        Object retVal = null;
        if (Long.class.getName().equals(fieldTypeClass.getName())
                || long.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Long.parseLong(value.toString());
        } else if (Integer.class.getName().equals(fieldTypeClass.getName())
                || int.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Integer.parseInt(value.toString());
        } else if (Float.class.getName().equals(fieldTypeClass.getName())
                || float.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Float.parseFloat(value.toString());
        } else if (Double.class.getName().equals(fieldTypeClass.getName())
                || double.class.getName().equals(fieldTypeClass.getName())) {
            retVal = Double.parseDouble(value.toString());
        } else {
            retVal = value;
        }
        return retVal;
    }

    /**
     * 获取指定字段名称查找在class中的对应的Field对象(包括查找父类)
     *
     * @param clazz     指定的class
     * @param fieldName 字段名称
     * @return Field对象
     */
    private static Field getClassField(Class clazz, String fieldName) {
        if (Object.class.getName().equals(clazz.getName())) {
            return null;
        }
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.getName().equals(fieldName)) {
                return field;
            }
        }

        Class superClass = clazz.getSuperclass();
        if (superClass != null) {// 简单的递归一下
            return getClassField(superClass, fieldName);
        }
        return null;
    }



    public static void main(String[] args) throws Exception{

    }
}
